import base64
import datetime
import threading
import multiprocessing
import os
import logging

import cv2
import numpy as np

from . import config

from backend.tools.infer import utility
from backend.tools.infer.predict_system import TextSystem


thread_lock = threading.Lock()
LOG = logging.getLogger(__name__)
process_lock = multiprocessing.Lock()


class OcrModel:
    def __init__(self):
        self.mode = self.load_text_recogniser_model()

    # 加载文本检测+识别模型
    def load_text_recogniser_model(self):
        # 获取参数对象
        args = utility.parse_args()
        # 是否使用GPU加速
        args.use_gpu = config.USE_GPU
        if config.USE_GPU:
            # 设置文本检测模型路径
            args.det_model_dir = config.DET_MODEL_PATH
            # 设置文本识别模型路径
            args.rec_model_dir = config.REC_MODEL_PATH
        else:
            # 加载快速模型
            args.det_model_dir = config.DET_MODEL_FAST_PATH
            # 加载快速模型
            # args.rec_model_dir = config.REC_MODEL_FAST_PATH
            args.rec_model_dir = config.REC_MODEL_PATH
        # 设置字典路径
        args.rec_char_dict_path = config.DICT_PATH
        LOG.error('args={}'.format(args))
        return TextSystem(args)

    def get_text(self, base64_img):
        dt_box, rec_res = self.mode(base64_img)
        coordinates = get_coordinates(dt_box)
        text_res = [(res[0], res[1]) for res in rec_res]
        result = [(coordinate, content[0]) for content, coordinate in zip(text_res, coordinates)]
        return result

    def get_text_from_filepath(self, filepath):
        img = cv2.imread(filepath)
        return self.get_text(img)

    def get_text_from_base64(self, img):
        img = base64.b64decode(img)
        image_data = np.frombuffer(img, np.uint8)
        img_decode = cv2.imdecode(image_data, cv2.IMREAD_COLOR)
        return self.get_text(img_decode)

    def get_text_from_bytes(self, content):
        image_data = np.frombuffer(content, np.uint8)
        img_decode = cv2.imdecode(image_data, cv2.IMREAD_COLOR)
        return self.get_text(img_decode)


def get_now_day():
    return datetime.datetime.now().strftime("%Y-%m-%d")


def get_local_file():
    input_dir = os.path.join(os.path.dirname(__file__), 'input')
    if not os.path.exists(input_dir):
        os.makedirs(input_dir)
    input_list = [
        file_name
        for file_name in os.listdir(input_dir)
    ]
    return input_list


def make_dirs_if_not_exist(path: str):
    path = os.path.abspath(path)
    with process_lock:
        with thread_lock:
            if not os.path.exists(path):
                os.makedirs(path)


def base64_to_image(base64_code):
    # base64解码
    img_data = base64.b64decode(base64_code)
    # 转换为np数组
    img_array = np.fromstring(img_data, np.uint8)
    # 转换成opencv可用格式
    img = cv2.imdecode(img_array, cv2.COLOR_RGB2BGR)
    return img


def get_coordinates(dt_box):
    """
    从返回的检测框中获取坐标
    :param dt_box 检测框返回结果
    :return list 坐标点列表
    """
    coordinate_list = list()
    if isinstance(dt_box, list):
        for i in dt_box:
            i = list(i)
            (x1, y1) = int(i[0][0]), int(i[0][1])
            (x2, y2) = int(i[1][0]), int(i[1][1])
            (x3, y3) = int(i[2][0]), int(i[2][1])
            (x4, y4) = int(i[3][0]), int(i[3][1])
            xmin = max(x1, x4)
            xmax = min(x2, x3)
            ymin = max(y1, y2)
            ymax = min(y3, y4)
            coordinate_list.append((xmin, xmax, ymin, ymax))
    return coordinate_list
